#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <stack>
#include <map>
#include <cstdlib>
using namespace std;

enum TOK_TYPE {
	TOK_KEYWORD,
	TOK_NONE,
	TOK_INT,
	TOK_STRING,
	TOK_STRING_CHAR,
	TOK_NAME,
	TOK_SMALL_BRACKET,
	TOK_BIG_BRACKET,
	TOK_SEMICOLON,
	TOK_OPERATOR,
	TOK_ASM,
};

typedef struct Lex {
    string token;
    unsigned int token_type;
} Lex;

typedef struct Variable {
    string type;
    vector<Lex> value;
} Variable;

void lexer(string code);
void generate_asm(vector<vector<Lex>> express);
void generate_asm_entry(string hoasm);
vector<Lex> reverse_polish(vector<Lex> infix_express, int start_index, int end_index);
void generate_boolean(vector<Lex> boolean_expr, int index);
void generate_express(Lex data1, Lex data2, Lex op);
string generate_var(string var_name);
void ast();
unsigned long long create_func_tree(unsigned long long i);
unsigned long long parse_boolean(unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_express(unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_sentence(string func_name, unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_asm(string func_name, unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_expr(string func_name, unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_if(string func_name, unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_else(string func_name, unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_while(string func_name, unsigned long long i, vector<Lex> *inner_expr);
unsigned long long parse_param_list(string func_name, unsigned long long i);
void append_lex(const string& token, int tok_type);

vector<Lex> lex_array;
vector<vector<Lex>> expr;
map<string, vector<vector<Lex>>> func_expr;
map<string, map<string, Variable>> func_vars;
map<string, Variable> vars;
map<string, unsigned int> int_vars;
stack<char> big_brackets;
string asm_code;
unsigned int label_index = 0;
map<string, int> priority;

bool is_keyword(const string& token) {
    return token == "function" ||
           token == "int" ||
           token == "string" ||
           token == "if" ||
           token == "elseif" ||
           token == "else" ||
           token == "while" ||
           token == "void" ||
           token == "__asm__";
}

bool is_operator(string str) {
    return str == "~" ||
           str == "!" ||
           str == "%" ||
           str == "^" ||
           str == "&" ||
           str == "&&" ||
           str == "*" ||
           str == "-" ||
           str == "+" ||
           str == "=" ||
           str == "==" ||
           str == "!=" ||
           str == "/" ||
           str == "<" ||
           str == "<=" ||
           str == "<<" ||
           str == ">" ||
           str == ">=" ||
           str == ">>" ||
           str == "|" ||
           str == "||" ||
           str == ",";
}

bool is_letter(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

bool is_digit(char c) {
    return c >= '0' && c <= '9';
}

bool is_space(char c) {
    return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}

bool is_type(string type) {
    vector<string> types;
    types.push_back("int");
    types.push_back("string");
    for (int i = 0; i < types.size(); i++) {
        if (type == types[i]) {
            return true;
        }
    }
    return false;
}

void append_lex(const string& token, int tok_type) {
    if (is_keyword(token)) {
        tok_type = TOK_KEYWORD;
    }
    Lex lex;
    lex.token = token;
    lex.token_type = tok_type;
    lex_array.push_back(lex);
}

unsigned long long parse_param_list(string func_name, unsigned long long i) {
    map<string, Variable> params;
    Variable var;
    string var_name;
    stack<Lex> var_stack;
    for (; i < lex_array.size() && lex_array[i].token != ")"; ) {
        if (lex_array[i].token_type == TOK_NAME) {
            if (!var_stack.empty()) {
                cout << "usage1: name type" << endl;
                exit(1);
            }
            var_stack.push(lex_array[i]);
            i++;
        } else if (lex_array[i].token_type == TOK_KEYWORD) {
            if (var_stack.size() % 2 == 0) {
                cout << "usage2: name type" << endl;
                exit(1);
            }
            var.type = lex_array[i].token;
            var_name = var_stack.top().token;
            var_stack.pop();
            params.insert(pair<string, Variable>(var_name, var));
            i++;
        } else if (lex_array[i].token == ",") {
            i++;
        } else {
            cout << "unknown identifier: " << lex_array[i].token << endl;
            exit(1);
        }
    }
    if (lex_array[i].token == ")") {
        if (var_stack.size() % 2 == 1) {
            cout << "usage3: name type" << endl;
            exit(1);
        }
    }
    if (!params.empty()) {
        func_vars[func_name] = params;
    }
    i++;
    return i;
}

unsigned long long parse_boolean(unsigned long long i, vector<Lex> *inner_expr) {
    stack<char> small_brackets;
    small_brackets.push('(');
    Lex lex;
    while (i < lex_array.size() && !small_brackets.empty()) {
        if (lex_array[i].token_type == TOK_INT ||
            lex_array[i].token_type == TOK_STRING_CHAR ||
            lex_array[i].token_type == TOK_NAME ||
            is_operator(lex_array[i].token)) {
            inner_expr->push_back(lex_array[i]);
        } else if (lex_array[i].token == "(") {
            small_brackets.push('(');
        } else if (lex_array[i].token == ")") {
            if (!small_brackets.empty()) {
                small_brackets.pop();
                lex = lex_array[i];
            } else {
                cout << "boolean1 brackets failed" << endl;
                exit(1);
            }
        } else {
            cout << "boolean express failed" << endl;
            exit(1);
        }
        i++;
    }
    if (!small_brackets.empty()) {
        cout << "boolean2 brackets stack not empty" << endl;
        exit(1);
    }
    inner_expr->push_back(lex);
    return i;
}

unsigned long long parse_express(unsigned long long i, vector<Lex> *inner_expr) {
    stack<char> brackets;
    while (i < lex_array.size() &&
        lex_array[i].token != ";" &&
        lex_array[i].token != "," &&
        lex_array[i].token != ")") {
        if (is_operator(lex_array[i].token)) {
            inner_expr->push_back(lex_array[i]);
            i++;
        } else if (lex_array[i].token_type == TOK_NAME ||
            lex_array[i].token_type == TOK_INT) {
            inner_expr->push_back(lex_array[i]);
            i++;
        } else if (lex_array[i].token_type == TOK_STRING_CHAR) {
            inner_expr->push_back(lex_array[i]);
            i++;
            if (lex_array[i].token_type == TOK_STRING) {
                inner_expr->push_back(lex_array[i]);
                i++;
            }
            if (lex_array[i].token_type == TOK_STRING_CHAR) {
                inner_expr->push_back(lex_array[i]);
                i++;
            }
        } else if (lex_array[i].token == "(") {
            inner_expr->push_back(lex_array[i]);
            brackets.push('(');
            i++;
        } else if (lex_array[i].token == ")") {
            if (brackets.top() != '(') {
                cout << "lack '('" << endl;
                exit(1);
            }
            inner_expr->push_back(lex_array[i]);
            brackets.pop();
            i++;
        } else if (lex_array[i].token == "[") {
            inner_expr->push_back(lex_array[i]);
            brackets.push('[');
            i++;
        } else if (lex_array[i].token == "]") {
            if (brackets.top() != '[') {
                cout << "lack '['" << endl;
                exit(1);
            }
            inner_expr->push_back(lex_array[i]);
            brackets.pop();
            i++;
        } else {
            cout << "unknown operation: " << lex_array[i].token << endl;
            exit(1);
        }
    }
    inner_expr->push_back(lex_array[i]);
    if (!brackets.empty()) {
        cout << "parse_express remain '" << brackets.top() << "'" << endl;
        exit(1);
    }
    i++;
    return i;
}

unsigned long long parse_sentence(string func_name, unsigned long long i, vector<Lex> *inner_expr) {
    string name = lex_array[i].token;
    i++;
    if (lex_array[i].token == "(") {
        inner_expr->push_back(lex_array[i]);
        i++;
        if (i >= lex_array.size()) {
            cout << "lack1 ')'" << endl;
            exit(1);
        }
        while (lex_array[i].token != ")") {
            i = parse_express(i, inner_expr);
            if (i >= lex_array.size()) {
                cout << "lack2 ')'" << endl;
                exit(1);
            }
            if (lex_array[i].token == ",") {
                inner_expr->push_back(lex_array[i]);
                i++;
                if (i >= lex_array.size()) {
                    cout << "lack3 ')'" << endl;
                    exit(1);
                }
            }
        }
        inner_expr->push_back(lex_array[i]);
        i++;
        if (i >= lex_array.size() || lex_array[i].token != ";") {
            cout << "lack4 ';'" << endl;
            exit(1);
        }
        inner_expr->push_back(lex_array[i]);
        if (func_name == "") {
            expr.push_back(*inner_expr);
        } else {
            func_expr[func_name].push_back(*inner_expr);
        }
        inner_expr->clear();
        i++;
    } else {
        Variable var;
        if (is_type(lex_array[i].token)) {
            var.type = lex_array[i].token;
            i++;
        }
        if (lex_array[i].token == ";") {
            i++;
            return i;
        }
        if (lex_array[i].token == "=") {
            i++;
        }
        i = parse_express(i, inner_expr);
        var.value = *inner_expr;
        if (func_name == "") {
            vars[name] = var;
        } else {
            func_vars[func_name][name] = var;
        }
    }
    return i;
}

unsigned long long parse_asm(string func_name, unsigned long long i, vector<Lex> *inner_expr) {
    inner_expr->push_back(lex_array[i]);
    if (lex_array[i].token != "(") {
        cout << "usage1: __asm__(...);" << endl;
        exit(1);
    }
    i++;
    if (i >= lex_array.size()) {
        cout << "usage2: __asm__(...);" << endl;
        exit(1);
    }
    if (lex_array[i].token_type != TOK_ASM) {
        cout << "usage3: __asm__(...);" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    i++;
    if (i >= lex_array.size()) {
        cout << "usage4: __asm__(...);" << endl;
        exit(1);
    }
    if (lex_array[i].token != ")") {
        cout << "usage5: __asm__(...);" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    i++;
    if (i >= lex_array.size() || lex_array[i].token_type != TOK_SEMICOLON) {
        cout << "usage6: __asm__(...);" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    i++;
    return i;
}

unsigned long long parse_expr(string func_name, unsigned long long i, vector<Lex> *inner_expr) {
    for (; i < lex_array.size() && lex_array[i].token != "}"; ) {
        if (lex_array[i].token == "function") {
            if (func_name == "") {
                i = create_func_tree(i + 1);
            } else {
                cout << "expr function cannot in function" << endl;
                exit(1);
            }
        } else if (is_type(lex_array[i].token)) {
            cout << "expr type cannot at the first" << endl;
            exit(1);
        } else if (lex_array[i].token == "if" || lex_array[i].token == "elseif") {
            inner_expr->push_back(lex_array[i]);
            i = parse_if(func_name, i + 1, inner_expr);
        } else if (lex_array[i].token == "else") {
            inner_expr->push_back(lex_array[i]);
            i = parse_else(func_name, i + 1, inner_expr);
        } else if (lex_array[i].token == "while") {
            inner_expr->push_back(lex_array[i]);
            i = parse_while(func_name, i + 1, inner_expr);
        } else if (lex_array[i].token == "__asm__") {
            inner_expr->push_back(lex_array[i]);
            i = parse_asm(func_name, i + 1, inner_expr);
        } else if (lex_array[i].token_type == TOK_NAME) {
            inner_expr->push_back(lex_array[i]);
            i = parse_sentence(func_name, i, inner_expr);
        } else if (lex_array[i].token == "{") {
            inner_expr->push_back(lex_array[i]);
            big_brackets.push('{');
            i++;
        } else if (lex_array[i].token == "}") {
            if (big_brackets.top() != '{') {
                cout << "lack4 '{'" << endl;
                exit(1);
            } else {
                inner_expr->push_back(lex_array[i]);
                big_brackets.pop();
            }
        }
    }
    if (i < lex_array.size() && lex_array[i].token == "}" && !inner_expr->empty()) {
        if (func_name == "") {
            expr.push_back(*inner_expr);
        } else {
            func_expr[func_name].push_back(*inner_expr);
        }
        inner_expr->clear();
    }
    return i;
}

unsigned long long parse_if(string func_name, unsigned long long i, vector<Lex> *inner_expr) {
    if (lex_array[i].token != "(") {
        cout << "usage1: if (boolean) {\n    ...\n}" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    i = parse_boolean(i + 1, inner_expr);
    if (lex_array[i].token != "{") {
        cout << "usage2: if (boolean) {\n    ...\n}" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    big_brackets.push('{');
    i = parse_expr(func_name, i + 1, inner_expr);
    if (lex_array[i].token != "}") {
        cout << "usage3: if (boolean) {\n    ...\n}" << endl;
        exit(1);
    }
    big_brackets.pop();
    inner_expr->push_back(lex_array[i]);
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    i++;
    return i;
}

unsigned long long parse_else(string func_name, unsigned long long i, vector<Lex> *inner_expr) {
    if (lex_array[i].token != "{") {
        cout << "usage1: else {\n    ...\n}" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    i++;
    big_brackets.push('{');
    i = parse_expr(func_name, i, inner_expr);
    if (lex_array[i].token != "}") {
        cout << "usage2: else {\n    ...\n}" << endl;
        exit(1);
    }
    big_brackets.pop();
    inner_expr->push_back(lex_array[i]);
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    i++;
    return i;
}

unsigned long long parse_while(string func_name, unsigned long long i, vector<Lex> *inner_expr) {
    if (lex_array[i].token != "(") {
        cout << "usage1: while (boolean) {\n    ...\n}" << endl;
        exit(1);
    }
    inner_expr->push_back(lex_array[i]);
    i = parse_boolean(i + 1, inner_expr);
    if (lex_array[i].token != "{") {
        cout << "usage2: while (boolean) {\n    ...\n}" << endl;
        exit(1);
    }
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    big_brackets.push('{');
    i = parse_expr(func_name, i + 1, inner_expr);
    if (lex_array[i].token != "}") {
        cout << "usage3: while (boolean) {\n    ...\n}" << endl;
        exit(1);
    }
    big_brackets.pop();
    inner_expr->push_back(lex_array[i]);
    if (func_name == "") {
        expr.push_back(*inner_expr);
    } else {
        func_expr[func_name].push_back(*inner_expr);
    }
    inner_expr->clear();
    big_brackets.pop();
    return i;
}

unsigned long long create_func_tree(unsigned long long i) {
    if (i >= lex_array.size() || lex_array[i].token_type != TOK_NAME) {
        cout << "usage1: function name(params) type  {\n    ...\n}" << endl;
        exit(1);
    }
    string func_name = lex_array[i].token;
    i++;
    if (i >= lex_array.size() || lex_array[i].token != "(") {
        cout << "usage2: function name(params) type {\n    ...\n}" << endl;
        exit(1);
    }
    i++;
    i = parse_param_list(func_name, i);
    if (i >= lex_array.size() || lex_array[i].token_type != TOK_KEYWORD) {
        cout << "usage3: function name(params) type {\n    ...\n}" << endl;
        exit(1);
    }
    i++;
    if (i >= lex_array.size() || lex_array[i].token != "{") {
        cout << "usage4: function name(params) type {\n    ...\n}" << endl;
        exit(1);
    }
    big_brackets.push('{');
    i++;
    vector<Lex> inner_expr;
    for (; i < lex_array.size() && lex_array[i].token != "}"; ) {
        inner_expr.push_back(lex_array[i]);
        if (lex_array[i].token == "function") {
            cout << "function cannot in function" << endl;
            exit(1);
        } else if (is_type(lex_array[i].token)) {
            cout << "type cannot at the first" << endl;
            exit(1);
        } else if (lex_array[i].token == "if" || lex_array[i].token == "elseif") {
            i = parse_if(func_name, i + 1, &inner_expr);
        } else if (lex_array[i].token == "else") {
            i = parse_else(func_name, i + 1, &inner_expr);
        } else if (lex_array[i].token == "while") {
            i = parse_while(func_name, i + 1, &inner_expr);
        } else if (lex_array[i].token == "__asm__") {
            i = parse_asm(func_name, i + 1, &inner_expr);
        } else if (lex_array[i].token_type == TOK_NAME) {
            i = parse_sentence(func_name, i, &inner_expr);
        } else if (lex_array[i].token == "{") {
            big_brackets.push('{');
            i++;
        } else if (lex_array[i].token == "}") {
            if (big_brackets.top() != '{') {
                cout << "lack4 '{'" << endl;
                exit(1);
            } else {
                big_brackets.pop();
            }
        }
    }
    if (i < lex_array.size() && lex_array[i].token == "}") {
        inner_expr.push_back(lex_array[i]);
    }
    if (big_brackets.empty()) {
        if (!inner_expr.empty()) {
            func_expr[func_name].push_back(inner_expr);
        }
        inner_expr.clear();
    }
    i++;
    return i;
}

void ast() {
    vector<Lex> inner_expr;
    parse_expr("", 0ULL, &inner_expr);
}

vector<Lex> reverse_polish(vector<Lex> infix_express, int start_index, int end_index) {
    vector<Lex> ret_vec;
    stack<Lex> stack1;
    Lex left_bracket;
    for (int i = start_index; i <= end_index; i++) {
        if (infix_express[i].token_type == TOK_NAME ||
            infix_express[i].token_type == TOK_INT) {
            ret_vec.push_back(infix_express[i]);
        } else if (infix_express[i].token == "(") {
            stack1.push(infix_express[i]);
        } else if (infix_express[i].token == ")") {
            while (stack1.top().token != "(") {
                ret_vec.push_back(stack1.top());
                stack1.pop();
            }
            stack1.pop();
        } else if (is_operator(infix_express[i].token)) {
            step3:
            if (stack1.empty() || stack1.top().token == "(" ||
                priority[infix_express[i].token] > priority[stack1.top().token]) {
                stack1.push(infix_express[i]);
            } else {
                ret_vec.push_back(stack1.top());
                stack1.pop();
                goto step3;
            }
        }
    }
    while (!stack1.empty()) {
        ret_vec.push_back(stack1.top());
        stack1.pop();
    }
    return ret_vec;
}

void generate_asm(vector<vector<Lex>> express) {
    for (int i = 0; i < express.size(); i++) {
        if (express[i][2].token_type == TOK_ASM) {
            asm_code += express[i][2].token + ";\n";
        }
    }
}

void generate_asm_entry(string hoasm) {
    asm_code += "MOV $DS, #0d7167;\n";
    generate_asm(expr);
    ofstream ofs(hoasm.c_str());
    if (!ofs.is_open()) {
        cout << "cannot open " << hoasm << endl;
        exit(1);
    }
    ofs << asm_code;
    ofs.close();
}

void lexer(string code) {
    int code_len = code.length();
    string token;
    int tok_type = TOK_NONE;
    for (int i = 0; i < code_len;) {
        char c = code[i];
        string str;
        str += c;
        if (token == "__asm__") {
            append_lex(token, tok_type);
            token = "";
            if (c == '(') {
                append_lex("(", TOK_SMALL_BRACKET);
                i++;
                c = code[i];
                while (c != ')') {
                    token += c;
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                }
                append_lex(token, TOK_ASM);
                token = "";
                append_lex(")", TOK_SMALL_BRACKET);
            }
            i++;
        } else {
            if (c == '\'') {
                i++;
                if (i >= code_len) {
                    break;
                }
                c = code[i];
                while (c != '\n') {
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                }
            }
            if (tok_type == TOK_STRING) {
                if (c == '\\') {
                    token += c;
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                    token += c;
                } else if (c == '"') {
                    if (!token.empty()) {
                        append_lex(token, tok_type);
                        token = "";
                    }
                    tok_type = TOK_NONE;
                    append_lex("\"", TOK_STRING_CHAR);
                } else {
                    token += c;
                }
                i++;
                continue;
            }
            if (is_letter(c) || c == '_') {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                tok_type = TOK_NAME;
                while ((is_letter(c) || is_digit(c) || c == '_' ) && !is_space(c)) {
                    token += c;
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                }
            } else if (is_digit(c)) {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                tok_type = TOK_INT;
                while (is_digit(c) && !is_space(c)) {
                    token += c;
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                }
            } else if (is_operator(str)) {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                tok_type = TOK_OPERATOR;
                while (is_operator(str) && !is_space(c)) {
                    token += c;
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                }
            } else if (is_space(c)) {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                tok_type = TOK_NONE;
                while (is_space(c)) {
                    i++;
                    if (i >= code_len) {
                        break;
                    }
                    c = code[i];
                }
            } else if (c == '(' || c == ')') {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                string cs;
                cs += c;
                append_lex(cs, TOK_SMALL_BRACKET);
                i++;
            } else if (c == '{' || c == '}') {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                string cs;
                cs += c;
                append_lex(cs, TOK_BIG_BRACKET);
                i++;
            } else if (c == ';') {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                append_lex(";", TOK_SEMICOLON);
                i++;
            } else if (c == '"') {
                if (!token.empty()) {
                    append_lex(token, tok_type);
                    token = "";
                }
                append_lex("\"", TOK_STRING_CHAR);
                tok_type = TOK_STRING;
                i++;
            } else {
                token += c;
                i++;
            }
        }
    }
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        cout << "usage: " << argv[0] << " hoc_file hoasm_file" << endl;
        return 1;
    }
    ifstream ifs;
    ifs.open(argv[1], ios::in);
    if (!ifs.is_open()) {
        cout << "文件打开失败" << endl;
        return 1;
    }
    string code;
    string buf;
    while (getline(ifs,buf)) {
        code += buf;
    }
    ifs.close();
    lexer(code);
    ast();
    string output_file = argv[2];
    priority.insert(pair<string, int>("=", 1));
    priority.insert(pair<string, int>("||", 2));
    priority.insert(pair<string, int>("&&", 3));
    priority.insert(pair<string, int>("|", 4));
    priority.insert(pair<string, int>("^", 5));
    priority.insert(pair<string, int>("&", 6));
    priority.insert(pair<string, int>("!=", 7));
    priority.insert(pair<string, int>("==", 7));
    priority.insert(pair<string, int>(">", 8));
    priority.insert(pair<string, int>(">=", 8));
    priority.insert(pair<string, int>("<", 8));
    priority.insert(pair<string, int>("<=", 8));
    priority.insert(pair<string, int>("<<", 9));
    priority.insert(pair<string, int>(">>", 9));
    priority.insert(pair<string, int>("+", 10));
    priority.insert(pair<string, int>("-", 10));
    priority.insert(pair<string, int>("*", 11));
    priority.insert(pair<string, int>("/", 11));
    priority.insert(pair<string, int>("%", 11));
    priority.insert(pair<string, int>("~", 12));
    generate_asm_entry(output_file);
    return 0;
}
